package com.xiguaji.tiktok.v1.product.controller;

import cn.hutool.core.date.DateUtil;
import com.paypal.http.HttpClient;
import com.paypal.http.HttpResponse;
import com.xiguaji.boot.toolkit.HttpUtil;
import com.xiguaji.tiktok.config.Config;
import com.xiguaji.tiktok.config.exception.ParamsException;
import com.xiguaji.tiktok.utils.Ret;
import com.xiguaji.tiktok.utils.guojipay.CallBackRequest;
import com.xiguaji.tiktok.utils.guojipay.CreateOrderRequest;
import com.xiguaji.tiktok.utils.guojipay.GuoJiPayUtil;
import com.xiguaji.tiktok.utils.guojipay.OrderResponse;
import com.xiguaji.tiktok.utils.paypal.core.PayPalEnvironment;
import com.xiguaji.tiktok.utils.paypal.core.PayPalHttpClient;
import com.xiguaji.tiktok.utils.paypal.orders.*;
import com.xiguaji.tiktok.v1.BaseController;
import com.xiguaji.tiktok.v1.product.dto.CreateOrderRst;
import com.xiguaji.tiktok.v1.product.dto.PayEnum;
import com.xiguaji.tiktok.v1.product.dto.PayResultRst;
import com.xiguaji.tiktok.v1.product.model.Product;
import com.xiguaji.tiktok.v1.product.model.ProductOrder;
import com.xiguaji.tiktok.v1.product.service.ProductService;
import com.xiguaji.tiktok.v1.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;

@RestController
@Api(value = "产品管理",tags = {"产品管理"})
@Slf4j
public class ProductController extends BaseController {

    @Autowired
    ProductService productService;

    @Autowired
    UserService userService;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    Config config;

    /*private PayPalEnvironment environment = new PayPalEnvironment.Sandbox(
            "Ad4WLaumFq5AHm8rKoSA3O7iAGfPcMVwL34mbssR982IGsuH1xhmGxdfirm82Ynl-nXdx9IqPJFLJeL-",
            "ENsMIWPr1oor23o10i1pHLU1kNV0LjlOZqhAgwCzY9nEGyKuCf4icrVh_HDkCv2QYQK5DQ-bQxdMcgBR");*/
    private PayPalEnvironment environment = new PayPalEnvironment.Live(
            "AWLEIYlKUuvbmfBohXkOsJjFrDglUH8IpIVFy0X2Z2hvOb5FTce8oOijeRp0jFIcN7ihdKvB0yEKtbfP",
            "EGFMTxnPAK4GiwQEsgX0qeGjWzXh7Ptx8Jmh2xTkN07_Es8o0zlOr6ozxCPsp9zXYp5ZvT0M2tHwrnUM");

    HttpClient client = new PayPalHttpClient(environment);


    @ApiOperation(value = "获取订单列表",notes = "获取订单列表")
    @RequestMapping(value = "order",method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    public String getOrderPage(String data) throws UnsupportedEncodingException, ParamsException {
        int page = getParam(Integer.class,URLDecoder.decode(data,"UTF-8"), "page");
        int pageSize = getParam(Integer.class,URLDecoder.decode(data,"UTF-8"),"pageSize");

        val userOrderPage = productService.getUserOrderPage(getUser().getId(), page, pageSize,null);
        return Ret.pageData(userOrderPage.getTotalCount(),userOrderPage.getList());
    }

    @ApiOperation(value = "获取版本商品",notes = "获取版本商品")
    @RequestMapping(value = "product",method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    public String getProducts(){
        return Ret.success("OK",productService.getVersionProductList(getUser().getId()));
    }

    @ApiOperation(value = "创建订单",notes = "创建订单")
    @RequestMapping(value="createOrder", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public String createOrder(@RequestBody CreateOrderRst createOrderRst) throws IOException{

        val product = productService.getProductById(createOrderRst.getProductId());
        ProductOrder basicOrder = null;
        if(product.getType().equals("version")){
            basicOrder = getVersionBasicOrder(product, createOrderRst.getMonthType(), createOrderRst.getPayType());
        }else if(product.getType().equals("report")){
            basicOrder = getReportBasicOrder(product, createOrderRst.getPayType());
        }

        if(basicOrder.getPrice().doubleValue() < -1){
            return Ret.err("支付金额为负数");
        }
        PayResultRst payResultRst;

        if(createOrderRst.getPayType() == PayEnum.payPal.getCode()){
            Order createdOrder = createPayPalOrder(client,basicOrder);
            payResultRst = new PayResultRst();
            payResultRst.setOrderId(createdOrder.id());
        }else if(createOrderRst.getPayType() == PayEnum.weChatPay.getCode() || createOrderRst.getPayType() == PayEnum.zfbPay.getCode()){
            payResultRst = createGuoJiPayOrder(basicOrder);
        }else {
            return Ret.err("找不到支付类型");
        }
        return Ret.success("OK!",payResultRst);
    }



    @ApiOperation(value = "查询订单状态",notes = "查询订单状态")
    @RequestMapping(value="order/status", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    public String orderStatus(String data) throws UnsupportedEncodingException, ParamsException {
        String paypalNumber = getParam(String.class, URLDecoder.decode(data,"UTF-8"),"paypalNumber");
        val productOrder = productService.getProductOrderByPaypalNumber(paypalNumber);

        if(null == productOrder){
            return Ret.err("Not Find Order");
        }
        return Ret.success("OK",productOrder);
    }

    @ApiOperation(value = "订单回调",notes = "订单回调")
    @RequestMapping(value="order/callback", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public void callbackOrder(@RequestBody String body) throws ParamsException, IOException {
        Map orderMap = getParam(Map.class,body);
        Map resource = (Map)orderMap.get("resource");
        val paypalNumber = resource.get("id").toString();
        val status = resource.get("status").toString();

        if(status.equals("COMPLETED")||status.equals("APPROVED")){
            productService.confirmProductOrder(paypalNumber);
        }
        /*OrdersCaptureRequest request = new OrdersCaptureRequest(paypalNumber);
        HttpResponse<Order> response = client.execute(request);
        response.statusCode();
        response.result();
        System.out.println("order response :"+response.result());
        Order order = response.result();
        System.out.println(order.toString());*/
    }

    /*@ApiOperation(value = "果集订单回调",notes = "果集订单回调")
    @RequestMapping(value="guoji/pay/callback", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public void callbackGuoJiPay(@RequestBody String body) throws ParamsException, IOException {
        String bodyStr = body.replaceAll("\uFEFF", "");
        Map order = JsonUtil.jsonParse(Map.class,bodyStr);
        val paypalNumber = order.get("OrderNo").toString();
        val status = Integer.parseInt(order.get("Result").toString());

        if(status == 2){
            productService.confirmProductOrder(paypalNumber);
        }
        *//*OrdersCaptureRequest request = new OrdersCaptureRequest(paypalNumber);
        HttpResponse<Order> response = client.execute(request);
        response.statusCode();
        response.result();
        System.out.println("order response :"+response.result());
        Order order = response.result();
        System.out.println(order.toString());*//*
    }*/

    @ApiOperation(value = "果集订单回调",notes = "果集订单回调")
    @RequestMapping(value="guoji/pay/callback", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public void callbackGuoJiPay(@RequestBody CallBackRequest callBackRequest){
        if(callBackRequest.getResult() == 2){
            productService.confirmProductOrder(callBackRequest.getOrderNo());
            log.info("果集支付完成！订单号:{},果集平台订单号:{}",callBackRequest.getOrderNo(),callBackRequest.getThirdOrderNo());
            return;
        }
        log.info("果集支付未完成！订单号:{},果集平台订单号:{}",callBackRequest.getOrderNo(),callBackRequest.getThirdOrderNo());
    }

    private ProductOrder getVersionBasicOrder(Product product,int monthType,int payType){
        ProductOrder productOrder = new ProductOrder();
        val userRole = userService.getUserRole(getUser().getId(), new Date());
        int month = 1;

        switch (monthType) {
            case 2:
                month = 6;
                double halfYearPrice = productService.getHalfYearPrice(product.getPrice(),1-product.getHalfYearDiscount());
                productOrder.setPrice(new BigDecimal(String.valueOf(halfYearPrice)));
                break;
            case 3:
                month = 12;
                double yearPrice = productService.getYearPrice(product.getPrice(),1-product.getYearDiscount());
                productOrder.setPrice(new BigDecimal(String.valueOf(yearPrice)));
                break;
            default:
                productOrder.setPrice(product.getPrice());
                break;
        }
        productOrder.setProductPrice(productOrder.getPrice());

        if(null != userRole && userRole.getRoleId() != product.getId()){
            val deductMoney = productService.getDeductMoney(userRole);
            productOrder.setPrice(new BigDecimal(String.valueOf(productService.getDeductPrice(productOrder.getPrice().setScale(2).doubleValue(),deductMoney))));
        }
        // productOrder.setPrice(new BigDecimal("0.001"));
        String orderPre = "PP_";
        if(payType == PayEnum.payPal.getCode()){
            orderPre = "PP_";
        }else if (payType == PayEnum.weChatPay.getCode()){
            orderPre = "WX_";
        } else if (payType == PayEnum.zfbPay.getCode()){
            orderPre = "ZFB_";
        }
        String orderNo = orderPre + DateUtil.format(new Date(),"yyyyMMddHHmmssSSS");
        productOrder.setOrderNumber(orderNo);
        productOrder.setUserId(getUser().getId());
        productOrder.setProductId(product.getId());
        productOrder.setCreateDate(new Date());
        productOrder.setProductName(product.getName());
        productOrder.setQty(month);
        productOrder.setStatus("0");
        productOrder.setPayType(payType);
        productOrder.setType(0);
        productOrder.setCreateBy("createVersionOrder");
        productOrder.setUpdateBy("createVersionOrder");
        return productOrder;
    }

    private ProductOrder getReportBasicOrder(Product product,int payType){
        ProductOrder productOrder = new ProductOrder();
        String orderPre = "PP_";
        if(payType == PayEnum.payPal.getCode()){
            orderPre = "PP_";
        }else if (payType == PayEnum.weChatPay.getCode()){
            orderPre = "WX_";
        } else if (payType == PayEnum.zfbPay.getCode()){
            orderPre = "ZFB_";
        }
        String orderNo = orderPre + DateUtil.format(new Date(),"yyyyMMddHHmmssSSS");
        productOrder.setOrderNumber(orderNo);
        productOrder.setPrice(new BigDecimal(productService.getDiscountPrice(product.getPrice(),1 - product.getDiscount() <= 0 ? 1:1 - product.getDiscount())));
        productOrder.setProductPrice(productOrder.getPrice());
        productOrder.setUserId(getUser().getId());
        productOrder.setProductId(product.getId());
        productOrder.setCreateDate(new Date());
        productOrder.setProductName(product.getName());
        productOrder.setQty(product.getNumber());
        productOrder.setStatus("0");
        productOrder.setPayType(payType);
        productOrder.setType(1);
        productOrder.setCreateBy("createReportOrder");
        productOrder.setUpdateBy("createReportOrder");
        return productOrder;

    }

    private Order createPayPalOrder(HttpClient client, ProductOrder productOrder) throws IOException {
        OrdersCreateRequest request = new OrdersCreateRequest();
        request.requestBody(buildRequestBody(productOrder));
        request.prefer("return=representation");
        HttpResponse<Order> response = client.execute(request);
        Order createdOrder = response.result();
        productOrder.setPaypalNumber(createdOrder.id());
        productService.saveOrder(productOrder);
        return createdOrder;
    }

    private PayResultRst createGuoJiPayOrder(ProductOrder productOrder){
        CreateOrderRequest orderRequest = new CreateOrderRequest();
        orderRequest.setProductId(config.getProductID());
        orderRequest.setOrderNo(productOrder.getOrderNumber());
        orderRequest.setName(productOrder.getProductName());
        orderRequest.setTotalFee(productOrder.getPrice().multiply(new BigDecimal(config.getUsdRate())).multiply(new BigDecimal(100)).intValue());
        // orderRequest.setTotalFee(1);
        orderRequest.setPayType(productOrder.getPayType());
        orderRequest.setClientIP(HttpUtil.getIp());
        orderRequest.setContent("产品购买");
        String sign = "";

        try {
            sign = GuoJiPayUtil.sign(orderRequest);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Sign",sign);
        HttpEntity<CreateOrderRequest> request = new HttpEntity<>(orderRequest, httpHeaders);
        // HttpEntity<String> request = new HttpEntity<>(JsonUtil.parseJson(httpHeaders), httpHeaders);
        ResponseEntity<OrderResponse> responseEntity = restTemplate.postForEntity(config.getGuoJiPayCreateUrl(),request, OrderResponse.class);
        if(responseEntity.getStatusCode() == HttpStatus.OK){
            OrderResponse orderResponse = responseEntity.getBody();
            if(orderResponse.getCode() == 0){
                // 回调时修改订单状态使用
                productOrder.setPaypalNumber(productOrder.getOrderNumber());
                productService.saveOrder(productOrder);
                PayResultRst payResultRst = new PayResultRst();
                payResultRst.setOrderId(orderResponse.getData().getOrderNo());
                payResultRst.setWeChatPayUrl(orderResponse.getData().getResult());
                return payResultRst;
            }
        }
        return null;

    }

    private OrderRequest buildRequestBody(ProductOrder productOrder) throws IOException {
        return new OrderRequest()
                .checkoutPaymentIntent("CAPTURE")
                .purchaseUnits(new ArrayList<>(){{
                    add(new PurchaseUnitRequest()
                            .referenceId(productOrder.getOrderNumber())
                            .amountWithBreakdown(new AmountWithBreakdown()
                                    .currencyCode("USD")
                                    .value(productOrder.getPrice().toString())));
                }});
    }
}
